#pragma once
#include "test_report.h"

using namespace krryn::test;

report_composite::report_composite(basic_report *a_First, basic_report *a_Second) : m_First(a_First), m_Second(a_Second) {}

report_composite::~report_composite(){
	delete m_First;
	delete m_Second;
}

void report_composite::test_begin(size_t a_Nr, const std::string &a_Name){
	m_First->test_begin(a_Nr, a_Name);
	m_Second->test_begin(a_Nr, a_Name);
}

void report_composite::test_end(size_t a_Nr, const result &a_Result, const std::string &a_Name){
	m_First->test_end(a_Nr, a_Result, a_Name);
	m_Second->test_end(a_Nr, a_Result, a_Name);
}

void report_composite::suite_begin(const std::string &a_Name){
	m_First->suite_begin(a_Name);
	m_Second->suite_begin(a_Name);
}

void report_composite::suite_end(const std::string &a_Name, size_t a_MaxTests){
	m_First->suite_end(a_Name, a_MaxTests);
	m_Second->suite_end(a_Name, a_MaxTests);
}

void report_composite::begin(size_t a_MaxTotal) {
	m_First->begin(a_MaxTotal);
	m_Second->begin(a_MaxTotal);
}

void report_composite::end() {
	m_First->end();
	m_Second->end();
}

report_stream::report_stream() : m_Output(std::cout) {}
report_stream::report_stream(std::ostream &a_Output) : m_Output(a_Output) {}

void report_stream::test_end(size_t a_Nr, const result &a_Result, const std::string &a_Name){
	const std::string l_Indent = "   ";

	if(!a_Result.skipped()){
		m_Results.push_back(a_Result);

		// provide feedback as soon as possible, in case we're running 
		// a large number of tests
		if(!a_Result.passed()){
			m_Output
				<< a_Result.m_Group << std::endl
				<< l_Indent << "test: " << a_Result.m_Nr
				<< (a_Result.m_Name.empty() ? "" : (std::string(" (") + a_Result.m_Name) + ")")
				<< std::endl;

			m_Output << l_Indent << "reason: ";

			switch(a_Result.m_Result){
				case result::fail:
					m_Output << "assertation failed";
					break;
			}

			m_Output << std::endl;

			if(!a_Result.m_Message.empty()){
				m_Output
					<< l_Indent << "message: '" << a_Result.m_Message << "'" 
					<< std::endl;
			}

			m_Output << std::endl;
		}
	}
}

void report_stream::end(){
	size_t l_Total = 0;
	size_t l_Failed = 0;

	for(result_list_t::iterator i = m_Results.begin(); i != m_Results.end(); i++){
		l_Total++;

		if(!i->passed()){
			l_Failed++;
		}
	}

	m_Output
		<< "Test cases run: " << l_Total 
		<< ", passed: " << (l_Total - l_Failed) 
		<< ", failed: " << l_Failed
		<< std::endl;
}